package com.xdth.sync.util;

import com.xdth.sync.command.SyncCommand;
import com.xdth.sync.model.DwInterface;
import com.xdth.sync.service.IDwInterfaceService;
import jodd.io.FileUtil;
import jodd.util.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;

import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * Created by dy on 17-7-3.
 */

public class SyncExecutor {
  public final Logger logger = LoggerFactory.getLogger(SyncExecutor.class);

  public static final String AVL = ".AVL";
  public static final String CHK = ".CHK";

  @Value("#{config['sync.n']}")
  private String syncN;
  @Value("#{config['sync.a']}")
  private String syncA;
  @Value("#{config['sync.a.package']}")
  private String syncPackageA;
  @Value("#{config['sync.b.package']}")
  private String syncPackageB;
  @Value("#{config['sync.data.dir']}")
  private String dataDir;

  ExecutorService fixedThreadPool = null;
  @Resource
  private IDwInterfaceService dwInterfaceService;
  @Resource
  private SyncCommand syncCommand;

  public SyncExecutor(int syncThreadNum) {
    fixedThreadPool = Executors.newFixedThreadPool(syncThreadNum);
  }

  public boolean executeSync(String fileName) {
    if (StringUtil.isNotEmpty(fileName)) {
      fixedThreadPool.submit(new SyncTask(fileName));
      return Boolean.TRUE;
    }
    return Boolean.FALSE;
  }

  class SyncTask implements Runnable {

    String fileName;

    public SyncTask(String fileName) {
      this.fileName = fileName;
    }

    @Override
    public void run() {
      String tableCode = tableCode(fileName);
      long startTime = System.currentTimeMillis()/1000;
      int actualRows=0;
      int targetRows=0;
      String log = null;
      String msg = null;
      DwInterface dwInterface = null;
      try{
        dwInterface = dwInterfaceService.findDwInterface(tableCode);
        if (null != dwInterface) {
          logger.info("开始同步[{}]数据, 数据文件[{}]", dwInterface.getInterfaceTable(), fileName);
          logger.info("truncate table {};", dwInterface.getInterfaceTable());
          dwInterfaceService.truncateTable(dwInterface.getInterfaceTable());
          // 执行 oracle sqlload 命令
          logger.info("开始执行oracle sqlload命令; 文件[{}]", fileName);
          syncCommand.exec(dwInterface.getInterfaceTable().toUpperCase()+tableCode, fileName);
          // 查询导入行数
          Long actualRowsTmp = dwInterfaceService.interfaceDataCount(dwInterface.getInterfaceTable());
          if(null != actualRowsTmp) {
            actualRows = actualRowsTmp.intValue();
          }
          //获取导入日志
          File logFile = new File(syncCommand.getLogPath(dwInterface.getInterfaceTable().toUpperCase()+tableCode));
          if (logFile.exists()) {
            log = FileUtil.readString(syncCommand.getLogPath(dwInterface.getInterfaceTable().toUpperCase()+tableCode));
          }
          dwInterfaceService.execProc(dwInterface.getSyncProc(),fileName.substring(0,1));
        }
      } catch (Exception e) {
        msg = e.getMessage();
        logger.error("执行数据同步出错,code=【{}】", tableCode, e);
      }

      try {
        targetRows = getTargetRows(fileName);
      } catch (Exception e) {
        logger.error("获取目标行数失败,code=【{}】", tableCode, e);
      }

      if(null != dwInterface) {
        try{
          dwInterfaceService.insertLog(fileName, Integer.valueOf(actualRows), Integer.valueOf(targetRows), startTime, StringUtil.isEmpty(msg), log, msg);
        }catch (Exception e) {
          logger.error("保存日志失败,code=【{}】", tableCode, e);
        }
      }

    }
  }

  int getTargetRows(String fileName) {
    if (StringUtil.isNotEmpty(fileName)) {
      String path = dataDir+fileName.replace(AVL, CHK);
      File file = new File(path);
      if (file.exists() && file.isFile()) {
        try {
          String chk = FileUtil.readString(file);
          String[] data = chk.split(",");
          if (data.length == 3) {
            return Integer.valueOf(data[1].trim()).intValue();
          }
        } catch (IOException e) {
          logger.error("读取检测文件[{}]失败", file.getPath(),  e);
        } catch (NumberFormatException nfe) {
          logger.error("读取检测文件行数[{}]失败", file.getPath(),  nfe);
        }
      }
    }
    return 0;
  }

  String tableCode(String fileName) {
    return fileName.substring(1, 6);
  }


  void shutdownAndAwaitTermination(ExecutorService pool) {
    pool.shutdown(); // Disable new tasks from being submitted
    try {
      // Wait a while for existing tasks to terminate
      if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
        pool.shutdownNow();
        if (!pool.awaitTermination(60, TimeUnit.SECONDS)) logger.error("Pool did not terminate");
      }
    } catch (InterruptedException ie) {
      pool.shutdownNow();
      Thread.currentThread().interrupt();
    }
  }


}
